package caidan.data;

import caidan.MainApp;
import jinyilw.common.SettingTools;
import jinyilw.common.math.MathTools;

import java.util.ArrayList;

public class FoodAssorter
{
	public static int maxPeppery = 4;
	public static int[] bMainDishIndexs;//早餐主菜（汤）
	public static int[] oMainDishIndexs;//午、晚餐主菜（汤）
	protected static CategoryData[] categoryDatas = MainApp.getCategoryDatas();
	private static final FoodData friedRiceData = FoodData
			.getData(categoryDatas[0].breakfastDatas, "炒米饭");
	private static final FoodData riceData = FoodData
			.getData(categoryDatas[0].otherDatas, "米饭");
	private static final FoodData bunData = FoodData
			.getData(categoryDatas[0].otherDatas, "馒头");
	private static final FoodData eggData = FoodData
			.getData(categoryDatas[0].breakfastDatas, "鸡蛋");
	private static final FoodData milkData = FoodData
			.getData(categoryDatas[0].breakfastDatas, "牛奶");

	public static final String[] rules = {"1.同一天主菜(汤)不重复", "2.同一餐主食材不重复",
			"3.同一餐辣度均衡", "4.同一餐口味多样", "5.同一餐颜色丰富", "6.考虑食材季节性", "7.早餐有炒米饭",
			"8.早餐有馒头", "9.早餐有鸡蛋", "10.早餐有牛奶", "11.午、晚餐有米饭", "12.午、晚餐有馒头"};
	public static final boolean[] checks = new boolean[rules.length];
	public static final String[] checkKeys = {"mainFoodNotRepeatInOneDay",
			"mainMaterialNotRepeatInOneMeal", "pepperyBalanced",
			"flavourVarious", "colorPlentiful", "accordCurrentSeason",
			"breakfastHasFriedRice", "breakfastHasBun", "breakfastHasEgg", "breakfastHasMilk",
			"otherHasRice", "otherHasBun"};

	static
	{
		calculateMainDishIndexes();
		for (int i = 0; i < checks.length; i++)
			checks[i] = SettingTools.getDefaultBool(checkKeys[i], true);
	}

	public static void calculateMainDishIndexes()
	{
		int n = 0;
		for (CategoryData categoryData : categoryDatas)
			if (categoryData.isMainDishes())
				n++;
		bMainDishIndexs = new int[n];
		oMainDishIndexs = new int[n];
		int j = 0, bIndex = 0, oIndex = 0;
		for (int i = 1; i < categoryDatas.length; i++)
		{
			if (categoryDatas[i].isMainDishes())
			{
				bMainDishIndexs[j] = bIndex;
				oMainDishIndexs[j] = oIndex;
				j++;
			}
			bIndex += categoryDatas[i].breakfastChooseNum;
			oIndex += categoryDatas[i].otherChooseNum;
		}
		//		for (int i : bMainDishIndexs)
		//			System.out.print(i + " ");
		//		System.out.println();
		//		for (int i : oMainDishIndexs)
		//			System.out.print(i + " ");
		//		System.out.println();
	}
	private final ArrayList<FoodData> breakfastDatas = new ArrayList<>();
	private final ArrayList<FoodData> lunchDatas = new ArrayList<>();
	private final ArrayList<FoodData> dinnerDatas = new ArrayList<>();
	private final int[][] bData, lData, dData;

	private int mealPeppery;

	public FoodAssorter()
	{
		int[] chooseNums = MainApp.breakfastChooseNums;
		bData = new int[categoryDatas.length][];
		for (int i = 0; i < bData.length; i++)
			bData[i] = new int[chooseNums[i]];
		chooseNums = MainApp.otherChooseNums;
		lData = new int[categoryDatas.length][];
		for (int i = 0; i < lData.length; i++)
			lData[i] = new int[chooseNums[i]];
		dData = new int[categoryDatas.length][];
		for (int i = 0; i < dData.length; i++)
			dData[i] = new int[chooseNums[i]];
	}

	//	public int[][] getBreakfastDatas()
	//	{
	//		return bData;
	//	}
	//
	//	public int[][] getLunchDatas()
	//	{
	//		return lData;
	//	}
	//
	//	public int[][] getDinnerDatas()
	//	{
	//		return dData;
	//	}

	public int[][] getDatas(int mealIndex)
	{
		if (mealIndex == 0)
			return bData;
		if (mealIndex == 1)
			return lData;
		return dData;
	}

	public synchronized void assortFood(int dayIndex)
	{
		for (int i = 0; i < bData.length; i++)
			for (int j = 0; j < bData[i].length; j++)
				bData[i][j] = -1;
		for (int i = 0; i < lData.length; i++)
			for (int j = 0; j < lData[i].length; j++)
				lData[i][j] = -1;
		for (int i = 0; i < dData.length; i++)
			for (int j = 0; j < dData[i].length; j++)
				dData[i][j] = -1;

		// oneDayDatas.clear();
		breakfastDatas.clear();
		lunchDatas.clear();
		dinnerDatas.clear();

		// System.out.println("mainFoodNotRepeatInOneDay:" + checks[0]);

		assort(breakfastDatas, bData, dayIndex, 0);
		assort(lunchDatas, lData, dayIndex, 1);
		assort(dinnerDatas, dData, dayIndex, 2);
		assortMain(breakfastDatas, bData, dayIndex, 0);
		assortMain(lunchDatas, lData, dayIndex, 1);
		assortMain(dinnerDatas, dData, dayIndex, 2);
	}

	boolean isConflict(ArrayList<FoodData> oneMealDatas, FoodData chooseData)
	{
		// 同一餐主食材不重复
		if (checks[1])
			if (chooseData.material.isMainMaterialSetted())
			{
				for (FoodData data : oneMealDatas)
					if (data.material.mainMaterial == chooseData.material.mainMaterial)
						return true;
			} else
			{
				for (FoodData data : oneMealDatas)
					if (data == chooseData)
						return true;
			}
		// 是否符合当前季节
		if (checks[5])
			if (chooseData.property.isSeasonConflict())
				return true;
		// 同一餐辣度均衡
		if (checks[2])
			if (chooseData.property.isPepperySetted())
				if (mealPeppery + chooseData.property.pepperyData > maxPeppery)
					return true;
		// 同一餐口味多样
		if (checks[3])
			if (chooseData.property.isFlavourConflict(oneMealDatas))
				return true;
		// 同一餐颜色丰富
		if (checks[4])
			if (chooseData.property.isColorConflict(oneMealDatas))
				return true;
		// 同一天主菜(汤)不重复
		if (!checks[0])
			return false;
		if (oneMealDatas == breakfastDatas)
			return false;
		int currentIndex = oneMealDatas.size();
		for (int i = 0; i < oMainDishIndexs.length; i++)
			if (currentIndex == oMainDishIndexs[i]
					&& breakfastDatas.get(bMainDishIndexs[i]) == chooseData)
				return true;

		if (oneMealDatas == lunchDatas)
			return false;

		for (int index : oMainDishIndexs)
			if (index == currentIndex && lunchDatas.get(index) == chooseData)
				return true;
		return false;
	}

	//	void assort(ArrayList<FoodData> oneMealDatas, int[][] data,
	//			boolean isBreakfast)
	//	{
	//		mealPeppery = 0;
	//		for (int i = 1; i < categoryDatas.length; i++)
	//		{
	//			ArrayList<FoodData> foodDatas = isBreakfast
	//					? categoryDatas[i].breakfastDatas
	//					: categoryDatas[i].otherDatas;
	//			int chooseNum = data[i].length;
	//			int size = foodDatas.size();
	//			int n = 0, random;
	//			FoodData chooseData;
	//			while (n < chooseNum)
	//			{
	//				random = (int) (Math.random() * size);
	//				chooseData = foodDatas.get(random);
	//				if (!isConflict(oneMealDatas, chooseData))
	//				{
	//					oneMealDatas.add(chooseData);
	//					if (chooseData.property.isPepperySetted())
	//						mealPeppery += chooseData.property.pepperyData;
	//					data[i][n] = random;
	//					n++;
	//				}
	//			}
	//		}
	//	}

	void assort(ArrayList<FoodData> oneMealDatas, int[][] data, int dayIndex,
			int mealIndex)
	{
		mealPeppery = 0;
		for (int i = 1; i < categoryDatas.length; i++)
		{
			ArrayList<FoodData> foodDatas = mealIndex == 0
					? categoryDatas[i].breakfastDatas
					: categoryDatas[i].otherDatas;
			int chooseNum = data[i].length;
			// int size = foodDatas.size();
			int[] indexs = getFoodDataIndexs(categoryDatas[i], dayIndex,
					mealIndex);
			if (indexs == null)
				continue;
			int n = 0, j = 0, index;
			FoodData chooseData;
			while (n < chooseNum && j < indexs.length)
			{
				index = indexs[j];
				j++;
				chooseData = foodDatas.get(index);
				if (!isConflict(oneMealDatas, chooseData))
				{
					oneMealDatas.add(chooseData);
					if (chooseData.property.isPepperySetted())
						mealPeppery += chooseData.property.pepperyData;
					data[i][n] = index;
					n++;
				}
			}
		}
	}

	protected int[] getFoodDataIndexs(CategoryData categoryData, int dayIndex,
			int mealIndex)
	{
		int size = mealIndex == 0
				? categoryData.breakfastDatas.size()
				: categoryData.otherDatas.size();
		return MathTools.getRandomDifferInts(size);
	}

	void assortMain(ArrayList<FoodData> oneMealDatas, int[][] data,
			int dayIndex, int mealIndex)
	{
		boolean isBreakfast = mealIndex == 0;
		ArrayList<FoodData> foodDatas = isBreakfast
				? categoryDatas[0].breakfastDatas
				: categoryDatas[0].otherDatas;
		int chooseNum = data[0].length;
		int n = 0, i = 0, index;
		int[] indexs = getFoodDataIndexs(categoryDatas[0], dayIndex, mealIndex);
		if (indexs == null)
			return;
		FoodData chooseData;
		boolean[] copyChecks = new boolean[checks.length];
		System.arraycopy(checks, 0, copyChecks, 0, checks.length);

		while1:
		while (n < chooseNum && i < indexs.length)
		{
			//早餐有炒米饭
			if (isBreakfast && copyChecks[6])
			{
				oneMealDatas.add(n, friedRiceData);
				data[0][n] = foodDatas.indexOf(friedRiceData);
				copyChecks[6] = false;
				n++;
				continue;
			}
			//早餐有馒头
			if (isBreakfast && copyChecks[7])
			{
				oneMealDatas.add(n, bunData);
				data[0][n] = foodDatas.indexOf(bunData);
				copyChecks[7] = false;
				n++;
				continue;
			}
			//早餐有馒头
			if (isBreakfast && copyChecks[8])
			{
				oneMealDatas.add(n, eggData);
				data[0][n] = foodDatas.indexOf(eggData);
				copyChecks[8] = false;
				n++;
				continue;
			}
			//早餐有馒头
			if (isBreakfast && copyChecks[9])
			{
				oneMealDatas.add(n, milkData);
				data[0][n] = foodDatas.indexOf(milkData);
				copyChecks[9] = false;
				n++;
				continue;
			}
			//午、晚餐有米饭
			if (!isBreakfast && copyChecks[10])
			{
				oneMealDatas.add(n, riceData);
				data[0][n] = foodDatas.indexOf(riceData);
				copyChecks[10] = false;
				n++;
				continue;
			}
			//午、晚餐有馒头
			if (!isBreakfast && copyChecks[11])
			{
				oneMealDatas.add(n, bunData);
				data[0][n] = foodDatas.indexOf(bunData);
				copyChecks[11] = false;
				n++;
				continue;
			}

			index = indexs[i];
			i++;
			chooseData = foodDatas.get(index);
			for (FoodData foodData : oneMealDatas)
				if (foodData == chooseData)
					continue while1;
			oneMealDatas.add(n, chooseData);
			data[0][n] = index;
			n++;
		}
	}
}
